﻿#include "service.h"
#include "requestqueue.h"
#include "requesttask.h"
#include "utils/utils.h"

namespace yc {

namespace {

static qreal download_speed = 100 * 1024; // kb/s
static qreal upload_speed = 100 * 1024;

}

Service::Service(QObject* parent) : QObject(parent)
{
    queue_ = new RequestQueue(5, this);
}

Service::~Service()
{
    delete queue_;
}

QNetworkAccessManager* Service::networkAccessManager() const
{
    return &queue_->networkAccessManager();
}

void Service::sendRequest(const Request request, const ResponseHandler& handler, bool logout,
                          int timeout)
{
    RequestTask* t = new RequestTask(request, handler, queue_, headers_, logout, timeout);
    connect(t, &RequestTask::authenticationRequired, this, &Service::authenticationRequired);
    if (QObject* receiver = handler.receiver()) {
        QPointer<Service> service;
        int id = request.seq();
        connect(receiver, &QObject::destroyed, this, [service, id] {
            if (service) {
                service->cancelRequest(id);
            }
        });
    }
    queue_->addTask(t);
}

void Service::cancelRequest(int seq)
{
    queue_->cancelRequest(seq);
}

int Service::getNextSeq()
{
    static int seq = 0;
    seq++;
    return seq;
}

void Service::setDownloadSpeed(qreal speed)
{
    download_speed = speed;
}

void Service::setUploadSpeed(qreal speed)
{
    upload_speed = speed;
}

qint64 Service::downloadCostMSecs(qint64 bytes_total)
{
    return qint64(download_speed > 0 ? 1000 * (bytes_total / download_speed) : 0);
}

qint64 Service::uploadCostMSecs(qint64 bytes_total)
{
    return qint64(upload_speed > 0 ? 1000 * (bytes_total / upload_speed) : 0);
}

void Service::setupRequest(QNetworkRequest& request, const QString& url,
                           const QString& content_type)
{
    RequestHeaders headers;
    setupRequest(request, baseutils::formatUrl(url), headers, content_type);
}

void Service::setupRequest(QNetworkRequest& request, const QString& url,
                           const RequestHeaders& headers, const QString& content_type)
{
    // ssl
    if (url.startsWith("https", Qt::CaseInsensitive)) {
        QSslConfiguration ssl_config;
        ssl_config.setPeerVerifyMode(QSslSocket::VerifyNone);
        ssl_config.setProtocol(QSsl::TlsV1_2OrLater);
        request.setSslConfiguration(ssl_config);
    }

    request.setHeader(QNetworkRequest::ContentTypeHeader, content_type);

    // headers
    for (auto it = headers.constBegin(), end = headers.constEnd(); it != end; it++) {
        request.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
    }

    request.setUrl(QUrl(baseutils::formatUrl(url)));
}
} // namespace yc
